<?php

/**
 * Synchronize Sales Quotes
 * 
 * @category   CRM4Ecommerce
 * @package    CRM4Ecommerce_VtigerSynchronization
 * @author     Philip Nguyen <philip@crm4ecommerce.com>
 * @link       http://crm4ecommerce.com
 */
class CRM4Ecommerce_VtigerSynchronization_Model_Synchronize_Quote extends CRM4Ecommerce_VtigerSynchronization_Model_Abstract {

    protected $_vtiger_model = 'Quotes';

    public function saveVtigerCurrencyRate(Mage_Sales_Model_Quote $quote, $vtiger_currency_rate) {
        $coreResource = Mage::getSingleton('core/resource');
        $sql = "UPDATE `" . $coreResource->getTableName('sales_flat_quote')
                . "` SET `vtiger_currency_rate` = '" . $vtiger_currency_rate . "'"
                . " WHERE `entity_id` = " . $quote->getId();

        $write = $coreResource->getConnection('core_write');
        $write->query($sql);
    }

    public function saveCurrencyCode(Mage_Sales_Model_Quote $quote, $quote_currency_code) {
        $coreResource = Mage::getSingleton('core/resource');
        $sql = "UPDATE `" . $coreResource->getTableName('sales_flat_quote')
                . "` SET `store_currency_code` = '" . $quote_currency_code . "', `quote_currency_code` = '" . $quote_currency_code . "'"
                . " WHERE `entity_id` = " . $quote->getId();

        $write = $coreResource->getConnection('core_write');
        $write->query($sql);
    }

    public function saveCurrencyRate(Mage_Sales_Model_Quote $quote, $base_to_quote_rate) {
        $coreResource = Mage::getSingleton('core/resource');
        $sql = "UPDATE `" . $coreResource->getTableName('sales_flat_quote')
                . "` SET `store_to_quote_rate` = '" . $base_to_quote_rate . "', `base_to_quote_rate` = '" . $base_to_quote_rate . "'"
                . " WHERE `entity_id` = " . $quote->getId();

        $write = $coreResource->getConnection('core_write');
        $write->query($sql);
    }

    public function save(Mage_Sales_Model_Quote $quote, $customer_id = 0) {
        $quote_id = $quote->getId();
        if (!$customer_id) {
            $customer_id = $quote->getCustomerId();
        }
        if ((int) $customer_id > 0) {
            $this->_function = 'save';
            $is_empty = (int) $quote->getItemsQty() == 0;

            if (!is_null(Mage::getModel('core/session')->getQuoteCurrencyRate()) && floatval(Mage::getModel('core/session')->getQuoteCurrencyRate()) > 0) {
                $quote->setStoreToQuoteRate(Mage::getModel('core/session')->getQuoteCurrencyRate());
                $quote->setBaseToQuoteRate(Mage::getModel('core/session')->getQuoteCurrencyRate());
                $this->saveCurrencyRate($quote, Mage::getModel('core/session')->getQuoteCurrencyRate());
                Mage::getModel('core/session')->setQuoteCurrencyRate(null);
            }
            if (!is_null(Mage::getModel('core/session')->getQuoteCurrencyCode()) && Mage::getModel('core/session')->getQuoteCurrencyCode() != '') {
                $quote->setQuoteCurrencyCode(Mage::getModel('core/session')->getQuoteCurrencyCode());
                $quote->setStoreCurrencyCode(Mage::getModel('core/session')->getQuoteCurrencyCode());
                $this->saveCurrencyCode($quote, Mage::getModel('core/session')->getQuoteCurrencyCode());
                Mage::getModel('core/session')->setQuoteCurrencyCode(null);
            }

            $customer = Mage::getModel('customer/customer')->load($customer_id);
            $accountid = null;
            if ($customer->getId() > 0) {
                if ($customer->getVtigerId() == '') {
                    Mage::getModel('vtigersynchronization/synchronize_customer')->save($customer);
                    $customer = Mage::getModel('customer/customer')->load($customer_id);
                }

                if ($customer->getVtigerType() != 'Accounts') {
                    Mage::getModel('vtigersynchronization/synchronize_customer')->convertLead($customer);
                    $customer = Mage::getModel('customer/customer')->load($customer_id);
                }
                if ($customer->getVtigerId() == '') {
                    Mage::getModel('vtigersynchronization/synchronize_customer')->saveAccount($customer, true);
                    $customer = Mage::getModel('customer/customer')->load($customer_id);
                }
                $accountid = $customer->getVtigerId();
            }

            $mapping_fields = array(
                'subject' => Mage::getStoreConfig('crm4ecommerce_vtigersynchronization/sales_params_settings/quote_subject_prefix') . $quote_id
            );
            $currency_code = $quote->getQuoteCurrencyCode();
            $currency_id = Mage::getModel('vtigersynchronization/mapping_currency')->getVtigerId($currency_code);
            $currency_rate = 1;
            if (intval($currency_id) > 0) {
                $mapping_fields['currency_id'] = $currency_id;
                $currency_rate = Mage::getModel('directory/currency')->getCurrencyRates(Mage::app()->getBaseCurrencyCode(), $currency_code);
                $currency_rate = $currency_rate[$currency_code];
                $mapping_fields['conversion_rate'] = $currency_rate;
            }
            if (!$is_empty) {
                $items = $this->prepareItems($quote->getAllItems(), $currency_rate);
                $mapping_fields['items'] = $items;
            }

            $default_values = array();
            $totals = $quote->getTotals();
            $subtotal = $quote->getSubtotal();
            $tax = 0;
            if (isset($totals['tax'])) {
                $tax = $totals['tax']->getValue();
            }
            $discount = 0;
            if (isset($totals['discount'])) {
                $discount = $totals['discount']->getValue();
                $discount = floatval($discount) < 0 ? - $discount : $discount;
            }
            $shipping = 0;
            if (isset($totals['shipping'])) {
                $shipping = $totals['shipping']->getValue();
            }
            $grand_total = $quote->getGrandTotal();

            $mapping_fields['hdnSubTotal'] = $subtotal + $tax;
            $mapping_fields['hdnDiscountAmount'] = $discount;
            $mapping_fields['hdnS_H_Amount'] = $shipping;
            $mapping_fields['hdnGrandTotal'] = $grand_total;
            $mapping_fields['hdnTaxType'] = 'individual';
            if ($accountid != '') {
                $mapping_fields['account_id'] = $accountid;
            }

            $there_address = false;
            $quote_billing_mapping = Mage::getModel('vtigersynchronization/mapping_field')
                    ->loadMappingFields(CRM4Ecommerce_VtigerSynchronization_Helper_Data::MAPPING_FIELDS_QUOTE, CRM4Ecommerce_VtigerSynchronization_Model_Array_MappingObjectType::QUOTE_BILL);

            $bilads = $quote->getBillingAddress();
            foreach ($quote_billing_mapping as $mapping_field) {
                $value = '';
                switch ($mapping_field->getAttributeCode()) {
                    case 'country_id':
                        $value = Mage::getModel('directory/country')->load($bilads->getCountryId())->getName();
                        break;
                    default:
                        $value = $bilads->getData($mapping_field->getAttributeCode());
                        break;
                }
                if ($value == '') {
                    if ($mapping_field->getVtigerUsingDefault() == CRM4Ecommerce_VtigerSynchronization_Model_Array_DefaultValueMode::EVERY_TIME) {
                        $value = $mapping_field->getVtigerDefaultValue();
                    } else {
                        $default_values[$mapping_field->getVtigerColumn()] = array(
                            'value' => $mapping_field->getVtigerDefaultValue(),
                            'type' => $mapping_field->getVtigerUsingDefault()
                        );
                    }
                } else {
                    $there_address = true;
                }
                $mapping_fields[$mapping_field->getVtigerColumn()] = $value;
            }
            $addressId = $bilads->getCustomerAddressId();
            if (!$addressId) {
                $addressId = $customer->getDefaultBilling();
            }
            $address = Mage::getModel('customer/address')->load($addressId);
            $mapping_fields['contact_id'] = $address->getVtigerId();

            $quote_shipping_mapping = Mage::getModel('vtigersynchronization/mapping_field')
                    ->loadMappingFields(CRM4Ecommerce_VtigerSynchronization_Helper_Data::MAPPING_FIELDS_QUOTE, CRM4Ecommerce_VtigerSynchronization_Model_Array_MappingObjectType::QUOTE_SHIP);

            $shipads = $quote->getShippingAddress();
            foreach ($quote_shipping_mapping as $mapping_field) {
                $value = '';
                switch ($mapping_field->getAttributeCode()) {
                    case 'country_id':
                        $value = Mage::getModel('directory/country')->load($shipads->getCountryId())->getName();
                        break;
                    case 'shipping_method':
                        $value = $shipads->getShippingDescription();
                        break;
                    default:
                        $value = $shipads->getData($mapping_field->getAttributeCode());
                        break;
                }
                if ($value == '') {
                    if ($mapping_field->getVtigerUsingDefault() == CRM4Ecommerce_VtigerSynchronization_Model_Array_DefaultValueMode::EVERY_TIME) {
                        $value = $mapping_field->getVtigerDefaultValue();
                    } else {
                        $default_values[$mapping_field->getVtigerColumn()] = array(
                            'value' => $mapping_field->getVtigerDefaultValue(),
                            'type' => $mapping_field->getVtigerUsingDefault()
                        );
                    }
                } else if ($mapping_field->getAttributeCode() != 'weight' && $mapping_field->getAttributeCode() != 'free_shipping') {
                    $there_address = true;
                }
                $mapping_fields[$mapping_field->getVtigerColumn()] = $value;
            }

            $status = Mage::getStoreConfig('crm4ecommerce_vtigersynchronization/sales_params_settings/quote_stage_review_cart');
            if (!$quote->getIsActive()) {
                if ($quote->getReservedOrderId()) {
                    $order = Mage::getModel('sales/order')->loadByIncrementId($quote->getReservedOrderId());
                    switch ($order->getState()) {
                        case Mage_Sales_Model_Order::STATE_COMPLETE:
                            $status = Mage::getStoreConfig('crm4ecommerce_vtigersynchronization/sales_params_settings/quote_stage_closed_won');
                            break;
                        case Mage_Sales_Model_Order::STATE_CLOSED:
                        case Mage_Sales_Model_Order::STATE_CANCELED:
                            $status = Mage::getStoreConfig('crm4ecommerce_vtigersynchronization/sales_params_settings/quote_stage_closed_lost');
                            break;
                        default:
                            $status = Mage::getStoreConfig('crm4ecommerce_vtigersynchronization/sales_params_settings/quote_stage_order_created');
                    }
                } else {
                    $status = Mage::getStoreConfig('crm4ecommerce_vtigersynchronization/sales_params_settings/quote_stage_closed_lost');
                }
            } else {
                if ($is_empty) {
                    $status = Mage::getStoreConfig('crm4ecommerce_vtigersynchronization/sales_params_settings/quote_cart_empty');
                } else if ($there_address) {
                    $status = Mage::getStoreConfig('crm4ecommerce_vtigersynchronization/sales_params_settings/quote_stage_available');
                } else {
                    $status = Mage::getStoreConfig('crm4ecommerce_vtigersynchronization/sales_params_settings/quote_stage_review_cart');
                }
            }

            $quote_info_mapping = Mage::getModel('vtigersynchronization/mapping_field')
                    ->loadMappingFields(CRM4Ecommerce_VtigerSynchronization_Helper_Data::MAPPING_FIELDS_QUOTE, CRM4Ecommerce_VtigerSynchronization_Model_Array_MappingObjectType::QUOTE_INFO);
            $store = null;
            if ($quote->getStoreId() > 0) {
                $store = Mage::getModel('core/store')->load($quote->getStoreId());
            }

            foreach ($quote_info_mapping as $mapping_field) {
                $value = '';
                switch ($mapping_field->getAttributeCode()) {
                    case 'status':
                        $value = $status;
                        break;
                    case 'customer_name':
                        $value = $quote->getCustomerPrefix() . ' ' . $quote->getCustomerFirstname() . ' ' . $quote->getCustomerLastname();
                        break;
                    case 'currency_code':
                        $value = $quote->getQuoteCurrencyCode();
                        break;
                    case 'website_id':
                        if (!is_null($store)) {
                            $value = $store->getWebsite()->getName();
                        }
                        break;
                    case 'store_group_id':
                        if (!is_null($store)) {
                            $value = $store->getGroup()->getName();
                        }
                        break;
                    case 'store_id':
                        if (!is_null($store)) {
                            $value = $store->getName();
                        }
                        break;
                    default:
                        $value = $quote->getData($mapping_field->getAttributeCode());
                        break;
                }

                if ($value == '') {
                    if ($mapping_field->getVtigerUsingDefault() == CRM4Ecommerce_VtigerSynchronization_Model_Array_DefaultValueMode::EVERY_TIME) {
                        $value = $mapping_field->getVtigerDefaultValue();
                    } else {
                        $default_values[$mapping_field->getVtigerColumn()] = array(
                            'value' => $mapping_field->getVtigerDefaultValue(),
                            'type' => $mapping_field->getVtigerUsingDefault()
                        );
                    }
                }
                $mapping_fields[$mapping_field->getVtigerColumn()] = $value;
            }

            $quote_other_mapping = Mage::getModel('vtigersynchronization/mapping_field')
                    ->loadMappingFields(CRM4Ecommerce_VtigerSynchronization_Helper_Data::MAPPING_FIELDS_QUOTE, CRM4Ecommerce_VtigerSynchronization_Model_Array_MappingObjectType::NO_MAPPING);
            foreach ($quote_other_mapping as $mapping_field) {
                $value = '';
                if ($mapping_field->getVtigerUsingDefault() == CRM4Ecommerce_VtigerSynchronization_Model_Array_DefaultValueMode::EVERY_TIME) {
                    $value = $mapping_field->getVtigerDefaultValue();
                } else {
                    $default_values[$mapping_field->getVtigerColumn()] = array(
                        'value' => $mapping_field->getVtigerDefaultValue(),
                        'type' => $mapping_field->getVtigerUsingDefault(),
                        'no_mapping' => true
                    );
                }
                $mapping_fields[$mapping_field->getVtigerColumn()] = $value;
            }

            $mapping_fields['vtiger_id'] = $quote->getVtigerId();
            $mapping_fields['remote_id'] = $quote->getId();
            $mapping_fields['default_values'] = $default_values;
            $vtiger_id = $this->post($mapping_fields);
            $this->saveVtigerId('sales_flat_quote', 'entity_id', $quote_id, $vtiger_id);
            $this->saveVtigerCurrencyRate($quote, $quote->getStoreToQuoteRate());
            if (($quote->getVtigerId() != $vtiger_id) || (!$quote->getReservedOrderId() && Mage::getSingleton('core/session')->getSyncPotential())) {
                Mage::getModel('vtigersynchronization/synchronize_potential')->save($quote, $vtiger_id, $currency_rate, $there_address);
            }
            return $vtiger_id;
        }
    }

    private function getProductOptions(Mage_Sales_Model_Quote_Item $item) {
        $options = array();
        if ($optionIds = $item->getOptionByCode('option_ids')) {
            $options = array();
            foreach (explode(',', $optionIds->getValue()) as $optionId) {
                if ($option = $item->getProduct()->getOptionById($optionId)) {
                    $quoteItemOption = $item->getOptionByCode('option_' . $option->getId());

                    $group = $option->groupFactory($option->getType())
                            ->setOption($option)
                            ->setQuoteItemOption($quoteItemOption);

                    $options[] = array(
                        'label' => $option->getTitle(),
                        'value' => $group->getFormattedOptionValue($quoteItemOption->getValue()),
                        'print_value' => $group->getPrintableOptionValue($quoteItemOption->getValue()),
                        'option_id' => $option->getId(),
                        'option_type' => $option->getType(),
                        'custom_view' => $group->isCustomizedView()
                    );
                }
            }
        }
        if ($addOptions = $item->getOptionByCode('additional_options')) {
            $options = array_merge($options, unserialize($addOptions->getValue()));
        }
        return $options;
    }

    private function getConfigurableOptions(Mage_Sales_Model_Quote_Item $item) {
        $product = $item->getProduct();
        $attributes = $product->getTypeInstance(true)
                ->getSelectedAttributesInfo($product);
        return $attributes;
    }

    private function getBundleOptions(Mage_Sales_Model_Quote_Item $item) {
        $options = array();

        $product = $item->getProduct();
        $typeInstance = $product->getTypeInstance(true);

        $optionsQuoteItemOption = $item->getOptionByCode('bundle_option_ids');
        if ($optionsQuoteItemOption) {
            $bundleOptionsIds = unserialize($optionsQuoteItemOption->getValue());
            if ($bundleOptionsIds) {
                $optionsCollection = $typeInstance->getOptionsByIds($bundleOptionsIds, $product);

                $selectionsQuoteItemOption = $item->getOptionByCode('bundle_selection_ids');
                if ($selectionsQuoteItemOption) {
                    $selectionsCollection = $typeInstance->getSelectionsByIds(
                            unserialize($selectionsQuoteItemOption->getValue()), $product
                    );

                    $bundleOptions = $optionsCollection->appendSelections($selectionsCollection, true);
                    foreach ($bundleOptions as $bundleOption) {
                        if ($bundleOption->getSelections()) {
                            $option = array('label' => $bundleOption->getTitle(), "value" => array());
                            $bundleSelections = $bundleOption->getSelections();

                            foreach ($bundleSelections as $bundleSelection) {
                                $_qty = 0;
                                if ($selectionQty = $product->getCustomOption('selection_qty_' . $bundleSelection->getSelectionId())) {
                                    $_qty = $selectionQty->getValue();
                                }

                                $price = $product->getPriceModel()->getSelectionFinalPrice(
                                        $product, $bundleSelection, $item->getQty() * 1, $_qty
                                );

                                $option['value'][] = array(
                                    'label' => $_qty . ' x ' . $bundleSelection->getName() . ': ' . strip_tags(Mage::helper('core')->currency($price)),
                                    'title' => $bundleSelection->getName()
                                );
                            }

                            $options[] = $option;
                        }
                    }
                }
            }
        }
        return $options;
    }

    private function getLinks(Mage_Sales_Model_Quote_Item $item) {
        $itemLinks = array();
        if ($linkIds = $item->getOptionByCode('downloadable_link_ids')) {
            $product = $item->getProduct();
            $productLinks = $product->getTypeInstance(true)
                    ->getLinks($product);

            foreach (explode(',', $linkIds->getValue()) as $linkId) {
                if (isset($productLinks[$linkId])) {
                    $itemLinks[] = $productLinks[$linkId];
                }
            }
        }

        return $itemLinks;
    }

    private function prepareItems($items, $currency_rate = 1) {
        $_items = array();
        $i = 0;
        foreach ($items as $item) {
            if ($item instanceof Mage_Sales_Model_Quote_Item) {
                $product = Mage::getModel('catalog/product')->load($item->getProductId());
                if (($item->getProductType() == 'bundle' && $product->getPriceType() != Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED) || $item->getProductType() == Mage_Catalog_Model_Product_Type_Configurable::TYPE_CODE) {
                    continue;
                }
                $vtiger_id = null;
                try {
                    $vtiger_id = $product->getVtigerId();
                    if (is_null($vtiger_id) || $vtiger_id == '') {
                        throw new Exception();
                    }
                } catch (Exception $e) {
                    Mage::getModel('vtigersynchronization/observer')->catalogProductSaveAfter($product, true);
                    $product = Mage::getModel('catalog/product')->load($product->getId());
                    $vtiger_id = $product->getVtigerId();
                }
                $parent_item = $item->getParentItem();
                $parent_qty = 1;
                if (!is_null($parent_item)) {
                    if ($parent_item->getProductType() == 'bundle' && $parent_item->getProduct()->getPriceType() == Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED) {
                        continue;
                    } else {
                        if ($parent_item->getProductType() == 'bundle')
                            $parent_qty = $parent_item->getQty();
                    }
                }

                $productType = $item->getProductType();
                $comment = '';

                switch ($productType) {
                    case 'bundle':
                        $comment = "";
                        $options = array_merge($this->getBundleOptions($item), $this->getProductOptions($item));
                        if (count($options)) {
                            foreach ($options as $option) {
                                $comment .= $option['label'] . ":\n";
                                if (is_array($option['value'])) {
                                    foreach ($option['value'] as $value) {
                                        $comment .= "     " . $value['label'] . ",\n";
                                    }
                                } else {
                                    $comment .= "     " . $option['value'] . ",\n";
                                }
                            }
                        }
                        break;
                    case Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE:
                        $comment = "";
                        $options = $this->getProductOptions($item);
                        if (count($options)) {
                            foreach ($options as $option) {
                                $comment .= "-) " . $option['label'] . ": " . $option['value'] . ",\n";
                            }
                        }

                        $linkTitle = $item->getProduct()->getLinksTitle();
                        if ($linkTitle) {
                            $linkTitle = Mage::getStoreConfig(Mage_Downloadable_Model_Link::XML_PATH_LINKS_TITLE);
                        }
                        $comment .= "-) " . $linkTitle . ",\n";

                        $links = $this->getLinks($item);
                        foreach ($links as $link) {
                            if ($link instanceof Mage_Downloadable_Model_Link) {
                                $comment .= "        + " . $link->getTitle() . ",\n";
                            }
                        }
                        break;
                    default :
                        $comment = "";
                        $parent_item = $item->getParentItem();
                        if (!is_null($parent_item) && $parent_item->getProductType() == Mage_Catalog_Model_Product_Type_Configurable::TYPE_CODE) {
                            $options = array_merge($this->getConfigurableOptions($parent_item), $this->getProductOptions($parent_item));
                            if (count($options)) {
                                foreach ($options as $option) {
                                    $comment .= "-) " . $option['label'] . ": " . $option['value'] . ",\n";
                                }
                            }
                        } else {
                            $options = $this->getProductOptions($item);
                            if (count($options)) {
                                foreach ($options as $option) {
                                    $comment .= "-) " . $option['label'] . ": " . $option['value'] . ",\n";
                                }
                            }
                        }
                        break;
                }

                if (!is_null($parent_item) && $parent_item->getProductType() == Mage_Catalog_Model_Product_Type_Configurable::TYPE_CODE) {
                    $item = $parent_item;
                }
                $listprice = floatval($item->getVtigerListPrice());
                if (!$listprice) {
                    $listprice = floatval($item->getBasePrice());
                }
                $listprice *= $currency_rate;
                $price = $listprice;
                if (floatval($item->getCustomPrice()) > 0) {
                    $price = floatval($item->getCustomPrice());
                }
                $discount_amount = 0;
                $qty = $item->getQty() * $parent_qty;
                if ($listprice > $price) {
                    $discount_amount = ($listprice - $price) * floatval($qty);
                }
                $tax_class = Mage::getModel('tax/class')->load($product->getTaxClassId());
                $data = array(
                    'productid' => $vtiger_id,
                    'sequence_no' => (++$i),
                    'quantity' => $qty,
                    'listprice' => $listprice,
                    'discount_amount' => $discount_amount,
                    'tax' => floatval($item->getTaxPercent()),
                    'tax_class' => $tax_class->getClassName(),
                    'comment' => trim($comment, ",\n")
                );
                $_items['item' . $i] = $data;
            }
        }
        return $_items;
    }

    public function delete(Mage_Sales_Model_Quote $quote) {
        $vtiger_id = $quote->getVtigerId();
        if ($vtiger_id != '') {
            $this->_function = 'delete';
            $this->post(array(
                'remote_id' => $quote->getId(),
                'vtiger_id' => $vtiger_id
            ));
            Mage::getModel('vtigersynchronization/synchronize_potential')->closePotential($quote);
        }
    }

}